class Tag < ActiveRecord::Base

	attr_accessible :name, :synonyms, :related_tags, :created_by, :updated_by
	
	# Validations:
	VALID_TAG_REGEX = /[a-z\-#\s]+/i
	VALID_SYNONYM_REGEX = /(\[[a-z\-\s]+\])+,{0,1}\s*/i
	validates :name, presence: true, format: { with: VALID_TAG_REGEX }, 
		uniqueness: { case_sensitive: false }
	validates :synonyms, allow_nil: true, format: { with: VALID_SYNONYM_REGEX }

	# Relationships:
	has_and_belongs_to_many :documents
	#has_many :tags, through: :related_tags
	
	before_save do |tag| 
		tag.name = name.downcase
		tag.synonyms = synonyms.downcase unless tag.synonyms.nil?
	end
	
	def self.tags_to_string(tags)
		tags.map { |t| t.name }.join ', '
	end
	
	def self.string_to_tags(tag_string, current_user, document)
		names = tag_string.split(/,\s*/)		
		names.map { |name| Tag.find_or_create(name, current_user, document) }
	end
	
	# Finds or created the given tag and returns it. Follows a custom logic for tags, taking
	# synonyms into consideration.
	def self.find_or_create(name, current_user, document)
		tag = Tag.find(:first, conditions: [ 'lower(name) = ?', name.downcase] )
		
		# Not found? Check for first synonym
		# Synonyms are enclosed in [] to avoid matching only part of a tag, like 'project' and
		# 'project management'. The first could match the second, but not with '[project]'.
		if tag.nil?
			tag = Tag.where('lower(synonyms) LIKE ?', "%[#{name.downcase}]%").first
		end
		
		# Still not found? Create new tag!
		if tag.nil?
			tag = document.tags.build(name: name, created_by: current_user.id)
		end
		
		tag
	end
	
	def reference_count
		self.documents.count
	end
  
end
